home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 051-075 / 068 / mg1b / window.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  10KB  |  388 lines

  1. /*
  2.  *        Window handling.
  3.  */
  4. #include    "def.h"
  5.  
  6. /*
  7.  * Reposition dot in the current
  8.  * window to line "n". If the argument is
  9.  * positive, it is that line. If it is negative it
  10.  * is that line from the bottom. If it is 0 the window
  11.  * is centered (this is what the standard redisplay code
  12.  * does).  If GOSREC is undefined, default is 0, so it acts like GNU.
  13.  * If GOSREC is defined, with no argument it defaults to 1
  14.  * and works like in Gosling.
  15.  */
  16. /*ARGSUSED*/
  17. reposition(f, n, k) {
  18. #ifndef    GOSREC
  19.     curwp->w_force = ((f == FALSE) ? 0 : n) ;
  20. #else
  21.     curwp->w_force = n;
  22. #endif
  23.     curwp->w_flag |= WFFORCE;
  24.     sgarbf = TRUE;
  25.     return (TRUE);
  26. }
  27.  
  28. /*
  29.  * Refresh the display. A call is made to the
  30.  * "ttresize" entry in the terminal handler, which tries
  31.  * to reset "nrow" and "ncol". They will, however, never
  32.  * be set outside of the NROW or NCOL range. If the display
  33.  * changed size, arrange that everything is redone, then
  34.  * call "update" to fix the display. We do this so the
  35.  * new size can be displayed. In the normal case the
  36.  * call to "update" in "main.c" refreshes the screen,
  37.  * and all of the windows need not be recomputed.
  38.  * Note that when you get to the "display unusable"
  39.  * message, the screen will be messed up. If you make
  40.  * the window bigger again, and send another command,
  41.  * everything will get fixed!
  42.  */
  43. /*ARGSUSED*/
  44. refresh(f, n, k) {
  45.     register WINDOW    *wp;
  46.     register int    oldnrow;
  47.     register int    oldncol;
  48.  
  49.     oldnrow = nrow;
  50.     oldncol = ncol;
  51.     ttresize();
  52.     if (nrow!=oldnrow || ncol!=oldncol) {
  53.         wp = wheadp;            /* Find last.        */
  54.         while (wp->w_wndp != NULL)
  55.             wp = wp->w_wndp;
  56.         if (nrow < wp->w_toprow+3) {    /* Check if too small.    */
  57.             ewprintf("Display unusable");
  58.             return (FALSE);
  59.         }        
  60.         wp->w_ntrows = nrow-wp->w_toprow-2;
  61.         sgarbf = TRUE;
  62.         update();
  63.         if (kbdmop == NULL) ewprintf("New size %d by %d", nrow, ncol);
  64.     } else
  65.         sgarbf = TRUE;
  66.     return (TRUE);
  67. }
  68.  
  69. /*
  70.  * The command to make the next
  71.  * window (next => down the screen)
  72.  * the current window. There are no real
  73.  * errors, although the command does
  74.  * nothing if there is only 1 window on
  75.  * the screen.
  76.  */
  77. /*ARGSUSED*/
  78. nextwind(f, n, k) {
  79.     register WINDOW    *wp;
  80.  
  81.     if ((wp=curwp->w_wndp) == NULL)
  82.         wp = wheadp;
  83.     curwp = wp;
  84.     curbp = wp->w_bufp;
  85.     return (TRUE);
  86. }
  87.  
  88. /*
  89.  * This command makes the previous
  90.  * window (previous => up the screen) the
  91.  * current window. There arn't any errors,
  92.  * although the command does not do a lot
  93.  * if there is 1 window.
  94.  */
  95. /*ARGSUSED*/
  96. prevwind(f, n, k) {
  97.     register WINDOW    *wp1;
  98.     register WINDOW    *wp2;
  99.  
  100.     wp1 = wheadp;
  101.     wp2 = curwp;
  102.     if (wp1 == wp2)
  103.         wp2 = NULL;
  104.     while (wp1->w_wndp != wp2)
  105.         wp1 = wp1->w_wndp;
  106.     curwp = wp1;
  107.     curbp = wp1->w_bufp;
  108.     return (TRUE);
  109. }
  110.  
  111. /*
  112.  * This command makes the current
  113.  * window the only window on the screen.
  114.  * Try to set the framing
  115.  * so that "." does not have to move on
  116.  * the display. Some care has to be taken
  117.  * to keep the values of dot and mark
  118.  * in the buffer structures right if the
  119.  * distruction of a window makes a buffer
  120.  * become undisplayed.
  121.  */
  122. /*ARGSUSED*/
  123. onlywind(f, n, k) {
  124.     register WINDOW    *wp;
  125.     register LINE    *lp;
  126.     register int    i;
  127.  
  128.     while (wheadp != curwp) {
  129.         wp = wheadp;
  130.         wheadp = wp->w_wndp;
  131.         if (--wp->w_bufp->b_nwnd == 0) {
  132.             wp->w_bufp->b_dotp  = wp->w_dotp;
  133.             wp->w_bufp->b_doto  = wp->w_doto;
  134.             wp->w_bufp->b_markp = wp->w_markp;
  135.             wp->w_bufp->b_marko = wp->w_marko;
  136.         }
  137.         free((char *) wp);
  138.     }
  139.     while (curwp->w_wndp != NULL) {
  140.         wp = curwp->w_wndp;
  141.         curwp->w_wndp = wp->w_wndp;
  142.         if (--wp->w_bufp->b_nwnd == 0) {
  143.             wp->w_bufp->b_dotp  = wp->w_dotp;
  144.             wp->w_bufp->b_doto  = wp->w_doto;
  145.             wp->w_bufp->b_markp = wp->w_markp;
  146.             wp->w_bufp->b_marko = wp->w_marko;
  147.         }
  148.         free((char *) wp);
  149.     }
  150.     lp = curwp->w_linep;
  151.     i  = curwp->w_toprow;
  152.     while (i!=0 && lback(lp)!=curbp->b_linep) {
  153.         --i;
  154.         lp = lback(lp);
  155.     }
  156.     curwp->w_toprow = 0;
  157.     curwp->w_ntrows = nrow-2;        /* 2 = mode, echo.    */
  158.     curwp->w_linep  = lp;
  159.     curwp->w_flag  |= WFMODE|WFHARD;
  160.     return (TRUE);
  161. }
  162.  
  163. /*
  164.  * Split the current window. A window
  165.  * smaller than 3 lines cannot be split.
  166.  * The only other error that is possible is
  167.  * a "malloc" failure allocating the structure
  168.  * for the new window.
  169.  */
  170. /*ARGSUSED*/
  171. splitwind(f, n, k) {
  172.     register WINDOW    *wp;
  173.     register LINE    *lp;
  174.     register int    ntru;
  175.     register int    ntrd;
  176.     int        ntrl;
  177.     WINDOW        *wp1, *wp2;
  178.  
  179.     if (curwp->w_ntrows < 3) {
  180.         ewprintf("Cannot split a %d line window", curwp->w_ntrows);
  181.         return (FALSE);
  182.     }
  183.     if ((wp = (WINDOW *)malloc(sizeof(WINDOW))) == NULL) {
  184.         ewprintf("Can't get %d", sizeof(WINDOW));
  185.         return (FALSE);
  186.     }
  187.     ++curbp->b_nwnd;            /* Displayed twice.    */
  188.     wp->w_bufp  = curbp;
  189.     wp->w_dotp  = curwp->w_dotp;
  190.     wp->w_doto  = curwp->w_doto;
  191.     wp->w_markp = curwp->w_markp;
  192.     wp->w_marko = curwp->w_marko;
  193.     wp->w_flag  = 0;
  194.     wp->w_force = 0;
  195.     ntru = (curwp->w_ntrows-1) / 2;        /* Upper size        */
  196.     ntrl = (curwp->w_ntrows-1) - ntru;    /* Lower size        */
  197.     lp = curwp->w_linep;
  198.     ntrd = 0;
  199.     while (lp != curwp->w_dotp) {
  200.         ++ntrd;
  201.         lp = lforw(lp);
  202.     }
  203.     lp = curwp->w_linep;
  204.     if (ntrd <= ntru) {            /* Old is upper window.    */
  205.         if (ntrd == ntru)        /* Hit mode line.    */
  206.             lp = lforw(lp);
  207.         curwp->w_ntrows = ntru;
  208.         wp->w_wndp = curwp->w_wndp;
  209.         curwp->w_wndp = wp;
  210.         wp->w_toprow = curwp->w_toprow+ntru+1;
  211.         wp->w_ntrows = ntrl;
  212.     } else {                /* Old is lower window    */
  213.         wp1 = NULL;
  214.         wp2 = wheadp;
  215.         while (wp2 != curwp) {
  216.             wp1 = wp2;
  217.             wp2 = wp2->w_wndp;
  218.         }
  219.         if (wp1 == NULL)
  220.             wheadp = wp;
  221.         else
  222.             wp1->w_wndp = wp;
  223.         wp->w_wndp   = curwp;
  224.         wp->w_toprow = curwp->w_toprow;
  225.         wp->w_ntrows = ntru;
  226.         ++ntru;                /* Mode line.        */
  227.         curwp->w_toprow += ntru;
  228.         curwp->w_ntrows  = ntrl;
  229.         while (ntru--)
  230.             lp = lforw(lp);
  231.     }
  232.     curwp->w_linep = lp;            /* Adjust the top lines    */
  233.     wp->w_linep = lp;            /* if necessary.    */
  234.     curwp->w_flag |= WFMODE|WFHARD;
  235.     wp->w_flag |= WFMODE|WFHARD;
  236.     return (TRUE);
  237. }
  238.  
  239. /*
  240.  * Enlarge the current window.
  241.  * Find the window that loses space. Make
  242.  * sure it is big enough. If so, hack the window
  243.  * descriptions, and ask redisplay to do all the
  244.  * hard work. You don't just set "force reframe"
  245.  * because dot would move.
  246.  */
  247. /*ARGSUSED*/
  248. enlargewind(f, n, k) {
  249.     register WINDOW    *adjwp;
  250.     register LINE    *lp;
  251.     register int    i;
  252.  
  253.     if (n < 0)
  254.         return (shrinkwind(f, -n, KRANDOM));
  255.     if (wheadp->w_wndp == NULL) {
  256.         ewprintf("Only one window");
  257.         return (FALSE);
  258.     }
  259.     if ((adjwp=curwp->w_wndp) == NULL) {
  260.         adjwp = wheadp;
  261.         while (adjwp->w_wndp != curwp)
  262.             adjwp = adjwp->w_wndp;
  263.     }
  264.     if (adjwp->w_ntrows <= n) {
  265.         ewprintf("Impossible change");
  266.         return (FALSE);
  267.     }
  268.     if (curwp->w_wndp == adjwp) {        /* Shrink below.    */
  269.         lp = adjwp->w_linep;
  270.         for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
  271.             lp = lforw(lp);
  272.         adjwp->w_linep  = lp;
  273.         adjwp->w_toprow += n;
  274.     } else {                /* Shrink above.    */
  275.         lp = curwp->w_linep;
  276.         for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
  277.             lp = lback(lp);
  278.         curwp->w_linep  = lp;
  279.         curwp->w_toprow -= n;
  280.     }
  281.     curwp->w_ntrows += n;
  282.     adjwp->w_ntrows -= n;
  283.     curwp->w_flag |= WFMODE|WFHARD;
  284.     adjwp->w_flag |= WFMODE|WFHARD;
  285.     return (TRUE);
  286. }
  287.  
  288. /*
  289.  * Shrink the current window.
  290.  * Find the window that gains space. Hack at
  291.  * the window descriptions. Ask the redisplay to
  292.  * do all the hard work.
  293.  */
  294. shrinkwind(f, n, k) {
  295.     register WINDOW    *adjwp;
  296.     register LINE    *lp;
  297.     register int    i;
  298.  
  299.     if (n < 0)
  300.         return (enlargewind(f, -n, KRANDOM));
  301.     if (wheadp->w_wndp == NULL) {
  302.         ewprintf("Only one window");
  303.         return (FALSE);
  304.     }
  305.     /*
  306.      * Bit of flakiness - KRANDOM means it was an internal call, and
  307.      * to be trusted implicitly about sizes.
  308.      */
  309.     if (k != KRANDOM && curwp->w_ntrows <= n) {
  310.         ewprintf("Impossible change");
  311.         return (FALSE);
  312.     }
  313.     if ((adjwp=curwp->w_wndp) == NULL) {
  314.         adjwp = wheadp;
  315.         while (adjwp->w_wndp != curwp)
  316.             adjwp = adjwp->w_wndp;
  317.     }
  318.     if (curwp->w_wndp == adjwp) {        /* Grow below.        */
  319.         lp = adjwp->w_linep;
  320.         for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
  321.             lp = lback(lp);
  322.         adjwp->w_linep  = lp;
  323.         adjwp->w_toprow -= n;
  324.     } else {                /* Grow above.        */
  325.         lp = curwp->w_linep;
  326.         for (i=0; i<n && lp!=curbp->b_linep; ++i)
  327.             lp = lforw(lp);
  328.         curwp->w_linep  = lp;
  329.         curwp->w_toprow += n;
  330.     }
  331.     curwp->w_ntrows -= n;
  332.     adjwp->w_ntrows += n;
  333.     curwp->w_flag |= WFMODE|WFHARD;
  334.     adjwp->w_flag |= WFMODE|WFHARD;
  335.     return (TRUE);
  336. }
  337.  
  338. /*
  339.  * Delete current window. Call shrink-window to do the screen
  340.  * updating, then throw away the window.
  341.  */
  342. /*ARGSUSED*/
  343. delwind(f, n, k) {
  344.     register WINDOW    *wp, *nwp;
  345.  
  346.     wp = curwp;            /* Cheap...        */
  347.     /* shrinkwind returning false means only one window... */
  348.     if (shrinkwind(FALSE, wp->w_ntrows + 1, KRANDOM) == FALSE)
  349.         return FALSE;
  350.     if (--wp->w_bufp->b_nwnd == 0) {
  351.         wp->w_bufp->b_dotp  = wp->w_dotp;
  352.         wp->w_bufp->b_doto  = wp->w_doto;
  353.         wp->w_bufp->b_markp = wp->w_markp;
  354.         wp->w_bufp->b_marko = wp->w_marko;
  355.     }
  356.     /* since shrinkwind did't crap out, we know we have a second window */
  357.     if (wp == wheadp) wheadp = curwp = wp->w_wndp;
  358.     else if ((curwp = wp->w_wndp) == NULL) curwp = wheadp;
  359.     curbp = curwp->w_bufp;
  360.     for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
  361.         if (nwp->w_wndp == wp) {
  362.             nwp->w_wndp = wp->w_wndp;
  363.             break ;
  364.         }
  365.     free((char *) wp);
  366.     return TRUE;
  367. }
  368. /*
  369.  * Pick a window for a pop-up.
  370.  * Split the screen if there is only
  371.  * one window. Pick the uppermost window that
  372.  * isn't the current window. An LRU algorithm
  373.  * might be better. Return a pointer, or
  374.  * NULL on error.
  375.  */
  376. WINDOW    *
  377. wpopup() {
  378.     register WINDOW    *wp;
  379.  
  380.     if (wheadp->w_wndp == NULL
  381.     && splitwind(FALSE, 0, KRANDOM) == FALSE)
  382.         return (NULL);
  383.     wp = wheadp;                /* Find window to use    */
  384.     while (wp!=NULL && wp==curwp)
  385.         wp = wp->w_wndp;
  386.     return (wp);
  387. }
  388.